package com.jinxin.platform.cdacscontrolmgr.utils;

import com.jinxin.platform.cdacscontrolmgr.common.Constant;
import lombok.extern.slf4j.Slf4j;
import net.coobird.thumbnailator.Thumbnails;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;
import sun.misc.BASE64Encoder;

import javax.imageio.ImageIO;
import javax.imageio.stream.FileImageOutputStream;
import java.awt.image.BufferedImage;
import java.io.*;
import java.math.BigDecimal;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.util.Arrays;
import java.util.Base64;
import java.util.UUID;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * Description: apcos-acs
 * Created by 34759 on 2020/4/22 15:59
 */
@Slf4j
public class ImageUtils {

    private static String ImageFormat = "jpg";

    /**
     * 通过图片base64流判断图片等于多少字节
     * image 图片流
     */
    public static Integer imageSize(String str) {
        Integer equalIndex = str.indexOf("=");//2.找到等号，把等号也去掉
        if (str.indexOf("=") > 0) {
            str = str.substring(0, equalIndex);
        }
        Integer strLength = str.length();//3.原来的字符流大小，单位为字节
        return strLength - (strLength / 8) * 2;//4.计算后得到的文件流大小，单位为字节
    }


    /**
     * 精确计算base64字符串文件大小（单位：B）
     *
     * @param base64String
     * @return
     */
    public static long base64FileSize(String base64String) {
        /**检测是否含有base64,文件头)*/
        if (base64String.lastIndexOf(",") > 0) {
            base64String = base64String.substring(base64String.lastIndexOf(",") + 1);
        }
        /** 获取base64字符串长度(不含data:audio/wav;base64,文件头) */
        int size0 = base64String.length();
        /** 获取字符串的尾巴的最后10个字符，用于判断尾巴是否有等号，正常生成的base64文件'等号'不会超过4个 */
        String tail = base64String.substring(size0 - 10);
        /** 找到等号，把等号也去掉,(等号其实是空的意思,不能算在文件大小里面) */
        int equalIndex = tail.indexOf("=");
        if (equalIndex > 0) {
            size0 = size0 - (10 - equalIndex);
        }
        /** 计算后得到的文件流大小，单位为字节 */
        return size0 - ((long) size0 / 8) * 2;
    }

    /**
     * 十六进制转成图片
     *
     * @author Administrator
     */
    public static String saveToImgFile(String src, String output) {
        if (src == null || src.length() == 0) {
            return "";
        }
        try {
            createFile(new File(output));
            FileOutputStream out = new FileOutputStream(output);
            byte[] bytes = src.getBytes();
            for (int i = 0; i < bytes.length; i += 2) {
                out.write(charToInt(bytes[i]) * 16 + charToInt(bytes[i + 1]));
            }
            out.close();
            return output;
        } catch (Exception e) {
            log.error(e.toString());
            return "";
        }
    }

    private static void createFile(File file) {
        if (!file.exists()) {
            if (!file.getParentFile().exists()) {
                file.getParentFile().mkdirs();
            }
            try {
                file.createNewFile();
            } catch (IOException e) {
                log.error(e.toString());
            }
        }
    }

    private static int charToInt(byte ch) {
        int val = 0;
        if (ch >= 0x30 && ch <= 0x39) {
            val = ch - 0x30;
        } else if (ch >= 0x41 && ch <= 0x46) {
            val = ch - 0x41 + 10;
        }
        return val;
    }

    public static String getImageStr(String imgFile) {
        InputStream inputStream = null;
        byte[] data = null;
        try {
            inputStream = new FileInputStream(imgFile);
            data = new byte[inputStream.available()];
            inputStream.read(data);
            inputStream.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        BASE64Encoder encoder = new BASE64Encoder();
        return encoder.encode(data);
    }

    /**
     * 十六进制字节转字节数组
     * Creates byte array representation of HEX string.<br>
     * http://www.cnblogs.com/qgc88
     * @param s
     *            string to parse
     * @return
     */
    private static byte[] fromHexString(String s) {
        int length = s.length() / 2;
        byte[] bytes = new byte[length];
        for (int i = 0; i < length; i++) {
            bytes[i] = (byte) ((Character.digit(s.charAt(i * 2), 16) << 4) | Character
                    .digit(s.charAt((i * 2) + 1), 16));
        }
        return bytes;
    }

    //byte数组转图片 http://www.cnblogs.com/qgc88
    private static String byte2image(byte[] data,String path){
        if(data.length<3||path.equals("")) return "";
        FileImageOutputStream imageOutput = null;
        try{
            imageOutput = new FileImageOutputStream(new File(path));
            imageOutput.write(data, 0, data.length);
            return path;
        } catch(Exception ex) {
            log.error(ex.toString());
            return "";
        }finally {
            if (imageOutput != null){
                try {
                    imageOutput.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    public static void base64ToFile(String base64, String filePath) {
        try {
            byte[] bytes = com.alibaba.druid.util.Base64.altBase64ToByteArray(base64);
            //base解密
            File videoFile = new File(filePath);
            //输入文件
            FileOutputStream fos = new FileOutputStream(videoFile);
            fos.write(bytes, 0, bytes.length);
            fos.flush();
            fos.close();
        } catch (IOException e) {
        }
    }

//    public static void main(String[] args) {
//        String str = "ffd8ffe000104a46494600010100000100010000ffdb00c500140e0f120f0d14121012171514181e32211e1c1c1e3d2c2e243249404c4b47404645505a736250556d5645466488656d777b8182814e608d978c7d96737e817c011517171e1a1e3b21213b7c5346537c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c021517171e1a1e3b21213b7c5346537c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7cffc00011080040008003012200021101031102ffc401a20000010501010101010100000000000000000102030405060708090a0b100002010303020403050504040000017d01020300041105122131410613516107227114328191a1082342b1c11552d1f02433627282090a161718191a25262728292a3435363738393a434445464748494a535455565758595a636465666768696a737475767778797a838485868788898a92939495969798999aa2a3a4a5a6a7a8a9aab2b3b4b5b6b7b8b9bac2c3c4c5c6c7c8c9cad2d3d4d5d6d7d8d9dae1e2e3e4e5e6e7e8e9eaf1f2f3f4f5f6f7f8f9fa0100030101010101010101010000000000000102030405060708090a0b1100020102040403040705040400010277000102031104052131061241510761711322328108144291a1b1c109233352f0156272d10a162434e125f11718191a262728292a35363738393a434445464748494a535455565758595a636465666768696a737475767778797a82838485868788898a92939495969798999aa2a3a4a5a6a7a8a9aab2b3b4b5b6b7b8b9bac2c3c4c5c6c7c8c9cad2d3d4d5d6d7d8d9dae2e3e4e5e6e7e8e9eaf2f3f4f5f6f7f8f9faffdd00040000ffda000c03010002110311003f00c9bae13f1ab2ac8be5c78e76e6ab5efdd18f5ab291a9981cf2aa38a0082e4c6f03320e41c5528d77385f5356e750b0381fdfa86cc6eb84fad004b718b699760ea39aaece64624d59d487ef14fb55353cd005bb7b412a6e34f7b1c2921a94ca61b2429dea0fb6c84638a00aadd7157ed2";
//        saveToImgFile2(str,"D://111/2222/" + System.currentTimeMillis() + ".jpg");
//        String urlStr = "http://222.182.202.109:33728/upload/module/1660210138286/1660210138286/urFGr1hNdbeg95adc2b0ae8aeeb7ae1b9aab91e9c9ef.jpeg";
//        String savePath = "d://uploadFiles//cdacscontrolmgr";
//        String filePath = downLoadFromUrl(urlStr, savePath);
//        File file = new File(filePath);
//        System.out.println(file.length());
//        String faceBytes;
//        String base64FromFile = getBase64FromFile(filePath);
//        if(file.length() > 200*1024){
//            byte[] bytes = new byte[0];
//            try {
//                bytes = ImageUtils.commpressPicCycle(getBytes(filePath), 200, 0.5f);
//            } catch (IOException e) {
//                e.printStackTrace();
//            }
//            BASE64Encoder encoder = new BASE64Encoder();
//            faceBytes = encoder.encode(bytes).replaceAll("\r|\n", "");
//        }else {
//            faceBytes = getBase64FromFile(filePath);
//        }
//
//        base64ToFile("data:image/jpeg;base64,"+faceBytes,"C:\\Users\\那个男人\\Desktop\\888.jpg");
//    }

    /**
     * 从网络Url中下载文件
     *
     * @param urlStr
     * @param savePath
     * @throws IOException
     */
    public static String downLoadFromUrl(String urlStr, String savePath) {
        try {
            URL url = new URL(urlStr);
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            // 设置超时间为3秒
            conn.setConnectTimeout(3 * 1000);
            // 防止屏蔽程序抓取而返回403错误
            conn.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT; DigExt)");

            // 得到输入流
            InputStream inputStream = conn.getInputStream();
            // 获取自己数组
            byte[] getData = readInputStream(inputStream);

            // 文件保存位置
            File saveDir = new File(savePath);
            if (!saveDir.exists()) {
                saveDir.mkdir();
            }
            String fileName = StringUtil.getUuid();
            File file = new File(saveDir + File.separator + fileName);
            FileOutputStream fos = new FileOutputStream(file);
            fos.write(getData);
            if (fos != null) {
                fos.close();
            }
            if (inputStream != null) {
                inputStream.close();
            }
            // System.out.println("info:"+url+" download success");
            return saveDir + File.separator + fileName;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "";

    }

    /**
     * 将inputstream转为Base64
     *
     * @param filePath 文件路径
     * @return
     * @throws Exception
     */
    public static String getBase64FromFile(String filePath) {
        byte[] data = getBytes(filePath);
        if (data == null) return null;
        return StringUtil.getBase64String(data);
        //return replaceBlank(com.alibaba.druid.util.Base64.byteArrayToBase64(data));
    }

    /**
     * 将图片转换成Base64编码
     * @param imgFile 待处理图片地址
     * @return
     */
    public static String getImgBase(String imgFile) {
        // 将图片文件转化为二进制流
        InputStream in = null;
        byte[] data = null;
        // 读取图片字节数组
        try {
            in = new FileInputStream(imgFile);
            data = new byte[in.available()];
            in.read(data);
            in.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return Base64.getEncoder().encodeToString(data);
    }

    public static String getUrlImageToBase64(String requestUrl) {
        ByteArrayOutputStream data = new ByteArrayOutputStream();
        try {
            // 创建URL
            URL url = new URL(requestUrl);
            byte[] by = new byte[1024];
            // 创建链接
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            conn.setRequestMethod("GET");
            conn.setConnectTimeout(5 * 1000);
            InputStream is = conn.getInputStream();
            // 将内容读取内存中
            int len = -1;
            while ((len = is.read(by)) != -1) {
                data.write(by, 0, len);
            }
            // 关闭流
            is.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        // 对字节数组Base64编码
        Base64.Encoder encoder = Base64.getEncoder();
        return encoder.encodeToString(data.toByteArray());
    }

    public static void main(String[] args) {
        File file = new File("C:\\Users\\那个男人\\Desktop\\马1089.jpg");
        String base64 = Base64.getEncoder().encodeToString(fileToByte(file));
        //String base64 = getImgBase("C:\\Users\\那个男人\\Desktop\\马1089.jpg");
        System.out.println(base64);
        byte[] bytes = new byte[0];
        try {
            bytes = commpressPicCycle(fileToByte(file), 200, 0.5f);
        } catch (IOException e) {
            e.printStackTrace();
        }
        BASE64Encoder encoder = new BASE64Encoder();
        String faceBytes = encoder.encode(bytes);
        System.out.println(faceBytes);
//        System.out.println(getUrlImageToBase64("http://localhost:8083/%E9%A9%AC1089.jpg"));
    }

    public static byte[] getBytes(String filePath) {
        File file = new File(filePath);
        FileInputStream inputFile = null;
        try {
            inputFile = new FileInputStream(file);
        } catch (FileNotFoundException e) {
            log.error(e.toString());
        }
        if(inputFile == null){
            return null;
        }
        // 将文件转化为字节数组字符串，并对其进行Base64编码处理
        byte[] data = null;
        // 读取文件字节数组
        try {
            ByteArrayOutputStream swapStream = new ByteArrayOutputStream();
            byte[] buff = new byte[100];
            int rc = 0;
            while ((rc = inputFile.read(buff, 0, 100)) > 0) {
                swapStream.write(buff, 0, rc);
            }
            data = swapStream.toByteArray();
        } catch (IOException e) {
            log.error(e.toString());
        } finally {
            try {
                inputFile.close();
            } catch (IOException e) {
                log.error(e.toString());
            }
        }
        if(data == null){
            return null;
        }
        return data;
    }

    public static String replaceBlank(String str) {
        String dest = "";
        if (str!=null) {
            Pattern p = Pattern.compile("\\s*|\t|\r|\n");
            Matcher m = p.matcher(str);
            dest = m.replaceAll("");
        }
        return dest;
    }

    /**
     * 从输入流中获取字节数组
     *
     * @param inputStream
     * @return
     * @throws IOException
     */
    public static byte[] readInputStream(InputStream inputStream) throws IOException {
        byte[] buffer = new byte[1024];
        int len = 0;
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        while ((len = inputStream.read(buffer)) != -1) {
            bos.write(buffer, 0, len);
        }
        bos.close();
        return bos.toByteArray();
    }

    /**
     *
     * @param bytes 原图片字节数组
     * @param desFileSize 指定图片大小,单位 kb
     * @param accuracy 精度,递归压缩的比率,建议小于0.9
     * @return
     */
    public static byte[] commpressPicCycle(byte[] bytes, long desFileSize, double accuracy) throws IOException {
        // 获取目标图片
        long fileSize = bytes.length;
        log.info("=====fileSize======== "+fileSize);
        // 判断图片大小是否小于指定图片大小
        if(fileSize <= desFileSize * 1024){
            return bytes;
        }
        //计算宽高
        BufferedImage bim = ImageIO.read(new ByteArrayInputStream(bytes));
        int imgWidth = bim.getWidth();
        log.info(imgWidth+"====imgWidth=====");
        int imgHeight = bim.getHeight();
        int desWidth = new BigDecimal(imgWidth).multiply( new BigDecimal(accuracy)).intValue();
        log.info(desWidth+"====desWidth=====");
        int desHeight = new BigDecimal(imgHeight).multiply( new BigDecimal(accuracy)).intValue();
        ByteArrayOutputStream baos = new ByteArrayOutputStream(); //字节输出流（写入到内存）
        Thumbnails.of(new ByteArrayInputStream(bytes)).size(desWidth, desHeight).outputQuality(accuracy).toOutputStream(baos);
        //如果不满足要求,递归直至满足要求
        return commpressPicCycle(baos.toByteArray(), desFileSize, accuracy);
    }


    public static String saveToImgFile2(String str,String path){
        File filePth = new File(path);
        if(!filePth.getParentFile().exists()){
            filePth.getParentFile().mkdirs();
        }
        byte[] bytes = fromHexString(str);
        return byte2image(bytes,path);
    }

    /**
     * 文件File类型转BASE64
     *
     * @param file
     * @return
     */
    public static String multipartFileToBase64(String filePath,MultipartFile file) throws IOException {
        File tmpFile = new File(filePath + UUID.randomUUID()+ file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf(".")));
        file.transferTo(tmpFile);
        String base64 = Base64.getEncoder().encodeToString(fileToByte(tmpFile));
        if(tmpFile.exists()){tmpFile.delete();}
        return base64;
    }

    public static String getPreTypeByImgType(String imgType){
        if(StringUtils.isEmpty(imgType)){return "data:image/jpeg;base64,";}
        switch (imgType.toLowerCase()){
            case "png":return "data:image/png;base64,";
            case "gif":return "data:image/gif;base64,";
            case "svg":return "data:image/svg+xml;base64,";
            case "ico":return "data:image/x-icon;base64,";
            case "bmp":return "data:image/bmp;base64,";
            default:return "data:image/jpeg;base64,";
        }
    }

    /**
     * 文件File类型转byte[]
     *
     * @param file
     * @return
     */
    public static byte[] fileToByte(File file) {
        byte[] fileBytes = null;
        FileInputStream fis = null;
        try {
            fis = new FileInputStream(file);
            fileBytes = new byte[(int) file.length()];
            fis.read(fileBytes);
            fis.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return fileBytes;
    }

    private static int getBase64pos(byte[] afterBase64){
        int base64pos = 0;
        for (int i=0 ;i< afterBase64.length; i++) {
            String temp = Integer.toHexString( afterBase64[i] & 0xFF);
            if(Constant.ZERO.equals(temp)){
                base64pos = i;
                break;
            }
        }
        return base64pos;
    }

    public static void writeFile(String path, byte[] bytes) {
        try {
            File filePth = new File(path);
            if(!filePth.getParentFile().exists()){
                filePth.getParentFile().mkdirs();
            }
            FileOutputStream out = new FileOutputStream(path);//指定写到哪个路径中
            FileChannel fileChannel = out.getChannel();
            fileChannel.write(ByteBuffer.wrap(bytes)); //将字节流写入文件中
            fileChannel.force(true);//强制刷新
            fileChannel.close();
        } catch (IOException e) {
            e.printStackTrace();
            log.error("保存图片失败: " + e.toString());
            return;
        }
        log.info("保存图片成功");
    }

    public static void saveFile(String s,String path){
        byte[] afterBase64 = org.apache.commons.codec.binary.Base64.decodeBase64(s);
        int base64pos = getBase64pos(afterBase64);
        writeFile(path, Arrays.copyOfRange(afterBase64,base64pos+1,afterBase64.length));
    }

}
